package yu.zhou.njupt.importdataui.worker;

import java.io.File;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import yu.zhou.njupt.importdataui.core.Importer;
import yu.zhou.njupt.importdataui.core.impl.AccessImporter;
import yu.zhou.njupt.importdataui.core.impl.AccessImporter2;
import yu.zhou.njupt.importdataui.core.impl.CsvImporter;
import yu.zhou.njupt.importdataui.core.impl.XlsImporter;
import yu.zhou.njupt.importdataui.core.impl.XlsxImporter;
import yu.zhou.njupt.importdataui.entity.ImportResult;
import yu.zhou.njupt.importdataui.entity.enumtype.DoTruncate;
import yu.zhou.njupt.importdataui.entity.enumtype.NewImport;
import yu.zhou.njupt.importdataui.util.DbUtil;

/**
 * @author yu.zhou
 *
 */
public class Worker {

    Properties props = null;
    Document procedureDoc = null;
    Connection conn = null;
    File sourceFilePath = null;
    Map<String, Importer> importerMap = null;
    Map<String, String> fileTableMap = null; // 每个entry存放源文件名和源文件对应的表名
    List<String> validateTableNameList = null;
    List<String> unSupportedFileList = null;
    Map<String, ImportResult> successFileMap = null;
    List<String> failFileList = null;
    String dbName;
    
    public Worker(String dbName) throws Exception{
        this.dbName = dbName;
        init();
    }

    public Worker(String dbName, DoTruncate doTruncate, NewImport newImport) throws Exception{
        this.dbName = dbName;
        init();
    }

    protected void init() throws Exception{
        props = new Properties();

        props.load(Worker.class.getClassLoader().getResourceAsStream("config.properties"));
        
        procedureDoc = new SAXReader().read(Worker.class.getClassLoader().getResourceAsStream("procedure.xml"));

        conn = DbUtil.getConnection(props, dbName);
        sourceFilePath = new File(props.getProperty(dbName + ".sourceFilePath"));
        
        importerMap = new HashMap<String, Importer>();
        importerMap.put("csv", new CsvImporter(conn));
        importerMap.put("xls", new XlsImporter(conn));
        importerMap.put("xlsx", new XlsxImporter(conn));
        importerMap.put("mdb", new AccessImporter(conn));
        importerMap.put("mdb2", new AccessImporter2(conn));
        
        successFileMap = new HashMap<String, ImportResult>();
        failFileList = new ArrayList<String>();
        unSupportedFileList = new ArrayList<String>();
        fileTableMap = new HashMap<String, String>();
        validateTableNameList = new ArrayList<String>();
    }
    
    public void work() throws Exception {
        if (!sourceFilePath.exists()) {
            throw new Exception("指定的源文件目录不存在!!!!");
        } else {
            importData(sourceFilePath);
            
            /* 所有源文件的数据都导入成功，继续进行后续操作 */
            if ((unSupportedFileList.size() == 0) && (failFileList.size() == 0)) {
//                gatherTableStatistics(); // 收集统计信息
            } else {
                
            }
        }
        
        closeConnection();
    }
    
    /* 数据导入完成后收集表的统计信息 */
    protected void gatherTableStatistics() throws Exception {
        Element rootElement = procedureDoc.getRootElement();
        Element element = (Element) rootElement.element("gather_stats");
        String sql = element.getText();
        CallableStatement cs = conn.prepareCall(sql);
        cs.execute();
    }
    
    protected void importData(File file) {
        System.out.println("数据导入开始");
        
        importFile(file);
        
        System.out.println("数据导入结束.");
        System.out.println("不支持文件：");
        for (String filename : unSupportedFileList) {
            System.out.println("    " + filename);
        }
        System.out.println();
        
        System.out.println("成功的文件：");
        for (Entry<String, ImportResult> entry : successFileMap.entrySet()) {
            System.out.println("    " + entry.getKey() + "  记录数：" + entry.getValue().getRecordCount() + "  用时：" + entry.getValue().getElapsedTime() + "ms");
        }
        System.out.println();
        
        System.out.println("失败的文件：");
        for (String filename : failFileList) {
            System.out.println("    " + filename);
        }
    }
    
    /** 将源文件的数据导入到数据库的对应表中 */
    protected void importFile(File file) {
        for (File childFile : file.listFiles()) {
            if (childFile.isDirectory()) {
                importFile(childFile);
            } else {
                String filename = childFile.getName();
                if (validateTableNameList.contains(filename)) {
                    continue;
                }
                System.out.println("开始导入[" + childFile.getName() + "]...");
                ImportResult importResult = null;
                String fileTypeStr = "default";
                if (filename.lastIndexOf('.') != -1){
                    fileTypeStr = filename.substring(filename.lastIndexOf('.') + 1);
                };
                String lowerFileTypeStr = fileTypeStr.toLowerCase();
                
                if (importerMap.get(lowerFileTypeStr) != null) {
                    importResult = importerMap.get(lowerFileTypeStr).importData(childFile);
                    if (importResult.isSuccess()) {
                        System.out.println("[" + childFile.getName() + "]导入成功.");
                        successFileMap.put(childFile.getName(), importResult);
                    } else {
                        System.out.println("[" + childFile.getName()+ "]导入失败!!!!");
                        failFileList.add(childFile.getName());
                    }
                } else {
                    System.out.println("不支持该类型的文件");
                    unSupportedFileList.add(childFile.getName());
                }
            }
        }
    }

    protected void closeConnection() {
        DbUtil.closeConnection(conn);
    }

}